home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / ODF Release 3 / ODFDev / ODF / OS / FWMenu / FWMnuBar.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  21.1 KB  |  667 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWMnuBar.cpp
  4. //    Release Version:    $ ODF 3 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWMNUBAR_H
  13. #include "FWMnuBar.h"
  14. #endif
  15.  
  16. #ifndef FWPULLDM_H
  17. #include "FWPullDM.h"
  18. #endif
  19.  
  20. // ----- Foundation Includes -----
  21.  
  22. #ifndef FWSTRS_H
  23. #include "FWStrs.h"
  24. #endif
  25.  
  26. #ifndef FWSOMENV_H
  27. #include "FWSOMEnv.h"
  28. #endif
  29.  
  30. // ----- OS Includes -----
  31.  
  32. #ifndef FWRESOUR_H
  33. #include "FWResour.h"
  34. #endif
  35.  
  36. #ifndef FWMENUS_K
  37. #include "FWMenus.k"
  38. #endif
  39.  
  40. // ----- ODUtil Includes -----
  41.  
  42. #ifndef FWORDCOL_H
  43. #include "FWOrdCol.h"
  44. #endif
  45.  
  46. #ifndef _ITEXT_
  47. #include "IText.h"
  48. #endif
  49.  
  50. // ----- OpenDoc Includes -----
  51.  
  52. #ifndef SOM_ODPart_xh
  53. #include <Part.xh>
  54. #endif
  55.  
  56. #ifndef SOM_ODDraft_xh
  57. #include <Draft.xh>
  58. #endif
  59.  
  60. #ifndef SOM_ODStorageUnit_xh
  61. #include <StorageU.xh>
  62. #endif
  63.  
  64. #ifndef SOM_ODSession_xh
  65. #include <ODSessn.xh>
  66. #endif
  67.  
  68. #ifndef SOM_ODWindowState_xh
  69. #include <WinStat.xh>
  70. #endif
  71.  
  72. // ----- Macintosh Includes -----
  73.  
  74. #if defined(FW_BUILD_MAC) && !defined(__TOOLUTILS__)
  75. #include <ToolUtils.h>
  76. #endif
  77.  
  78. //========================================================================================
  79. //    RunTime Info
  80. //========================================================================================
  81.  
  82. #ifdef FW_BUILD_MAC
  83. #pragma segment fwmenu
  84. #endif
  85.  
  86. //========================================================================================
  87. //    class FW_CMenuBar
  88. //========================================================================================
  89.  
  90. FW_DEFINE_AUTO(FW_CMenuBar)
  91.  
  92. //----------------------------------------------------------------------------------------
  93. //    FW_CMenuBar::FW_CMenuBar
  94. //----------------------------------------------------------------------------------------
  95.  
  96. FW_CMenuBar::FW_CMenuBar(Environment* ev, ODPart* thePart, FW_Instance partInstance) :
  97.     fODPart(thePart),
  98.     fPullDownMenuList(NULL),
  99.     fNextMenuID(FW_kFirstMenuID),
  100.     fPartInstance(partInstance)
  101. {
  102.     fODMenuBar = fODPart->GetStorageUnit(ev)->GetSession(ev)->GetWindowState(ev)->CopyBaseMenuBar(ev);
  103.     fPullDownMenuList = FW_NEW(FW_TOrderedCollection<FW_CPullDownMenu>, ());
  104. }
  105.  
  106. //----------------------------------------------------------------------------------------
  107. //    FW_CMenuBar::InitializeFromResource
  108. //----------------------------------------------------------------------------------------
  109.  
  110. void FW_CMenuBar::InitializeFromResource(Environment* ev, FW_ResourceID menuBarResourceID)
  111. {
  112.     // InitializeFromResource should only be called once, immediately after
  113.     // the menu bar is created, while the menu list is still empty.
  114.     // However, since it simply appends the menus to the end of the menubar,
  115.     // there may be no harm in calling it more than once.
  116.     // FW_ASSERT(fPullDownMenuList->Count() == 0);
  117.  
  118.     FW_TRY
  119.     {
  120.         FW_PSharedLibraryResourceFile resFile(ev, fPartInstance);
  121.         FW_PResource menuBarResource(ev, resFile, menuBarResourceID, (FW_ResourceType)FW_kMenuBarResourceType);
  122.         FW_PResourceSink sink(ev, menuBarResource);
  123.         FW_CReadableStream stream(sink);
  124.         InitializeFromStream(ev, stream);
  125.     }
  126.     FW_CATCH_BEGIN
  127.     FW_CATCH_REFERENCE(FW_XException, except)
  128.     {
  129.         // We use this try-catch block purely to warn about a common mistake.
  130.         // If one forgets to add the resource containing their menus to their project,
  131.         // or passes in the wrong menu id, the above code will throw an exception
  132.         // that probably won't get caught until the SOM entry point from OpenDoc.
  133.         // OpenDoc will display an error dialog that isn't particularly helpful
  134.         // in diagnosing the problem.
  135.         FW_DEBUG_MESSAGE("Failed to load menu resource.");
  136.         FW_PlatformError error = except.GetPlatformError();
  137.         FW_THROW_SAME();
  138.     }
  139.     FW_CATCH_END
  140. }
  141.  
  142. //----------------------------------------------------------------------------------------
  143. //    FW_CMenuBar::InitializeFromStream
  144. //----------------------------------------------------------------------------------------
  145.  
  146. void FW_CMenuBar::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
  147. {
  148.     // InitializeFromStream should only be called once, immediately after
  149.     // the menu bar is created, while the menu list is still empty.
  150.     // However, since it simply appends the menus to the end of the menubar,
  151.     // there may be no harm in calling it more than once.
  152.     // FW_ASSERT(fPullDownMenuList->Count() == 0);
  153.  
  154.     // This first FW_DO_NOT_DEAD_STRIP is a must, so it makes full sense to have it here.
  155.     FW_DO_NOT_DEAD_STRIP(FW_CPullDownMenu);
  156.     
  157.     // These aren't absolutely required, but it would be extremely rare to have menu
  158.     // items without Text and Separators, so for convenience we prevent them from
  159.     // being dead stripped in any part that initializes its menus from a stream (resource).
  160.     // However, the other kinds of menu items must be explicitly prevented from being
  161.     // deadstripped in every part that uses them.
  162.     FW_DO_NOT_DEAD_STRIP(FW_CTextItem);
  163.     FW_DO_NOT_DEAD_STRIP(FW_CSeparatorItem);
  164.  
  165.     stream >> fAboutString;
  166.  
  167.     short nMenus;
  168.     stream >> nMenus;
  169.     
  170.     while (nMenus-- > 0)
  171.     {
  172.         FW_CPullDownMenu* pullDownMenu;
  173.         FW_READ_DYNAMIC_OBJECT(stream, &pullDownMenu, FW_CPullDownMenu);
  174.         FW_ASSERT(pullDownMenu != 0);
  175.         AdoptMenuLast(ev, pullDownMenu);
  176.     }
  177. }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. //    FW_CMenuBar::~FW_CMenuBar
  181. //----------------------------------------------------------------------------------------
  182.  
  183. FW_CMenuBar::~FW_CMenuBar()
  184. {
  185.     FW_SOMEnvironment ev;
  186.     
  187.     if (fPullDownMenuList)
  188.         DeleteAll(ev);
  189.  
  190.     if (fODMenuBar)
  191.         fODMenuBar->Release(ev);
  192. }
  193.  
  194. //----------------------------------------------------------------------------------------
  195. //    FW_CMenuBar::AdoptMenuFirst
  196. //----------------------------------------------------------------------------------------
  197.  
  198. void FW_CMenuBar::AdoptMenuFirst(Environment* ev, FW_CPullDownMenu* menu)
  199. {
  200.     FW_ASSERT(menu != NULL);
  201.     
  202.     FW_CPullDownMenu* first = (FW_CPullDownMenu*)fPullDownMenuList->First();
  203.     fPullDownMenuList->AddFirst(menu);
  204.     
  205.     ODMenuID beforeID = first == NULL ? -1 : first->GetMenuID(ev);    
  206.     menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeID);
  207. }
  208.  
  209. //----------------------------------------------------------------------------------------
  210. //    FW_CMenuBar::AdoptMenuLast
  211. //----------------------------------------------------------------------------------------
  212.  
  213. void FW_CMenuBar::AdoptMenuLast(Environment* ev, FW_CPullDownMenu* menu)
  214. {
  215.     FW_ASSERT(menu != NULL);
  216.     
  217.     fPullDownMenuList->AddLast(menu);    
  218.     menu->PrivAttachedToMenuBar(ev, fODPart, this, -1);
  219. }
  220.  
  221. //----------------------------------------------------------------------------------------
  222. //    FW_CMenuBar::AdoptMenuBefore
  223. //----------------------------------------------------------------------------------------
  224.  
  225. void FW_CMenuBar::AdoptMenuBefore(Environment* ev, FW_CPullDownMenu* menu, FW_CPullDownMenu* beforeMenu)
  226. {
  227.     FW_ASSERT(menu != NULL);
  228.  
  229.     if (beforeMenu == NULL)
  230.         AdoptMenuFirst(ev, menu);
  231.     else
  232.     {
  233.         fPullDownMenuList->AddBefore(beforeMenu, menu);
  234.         menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeMenu->GetMenuID(ev));
  235.     }
  236. }
  237.  
  238. //----------------------------------------------------------------------------------------
  239. //    FW_CMenuBar::AdoptMenuAfter
  240. //----------------------------------------------------------------------------------------
  241.  
  242. void FW_CMenuBar::AdoptMenuAfter(Environment* ev, FW_CPullDownMenu* menu, FW_CPullDownMenu* afterMenu)
  243. {
  244.     FW_ASSERT(menu != NULL);
  245.  
  246.     if (afterMenu == NULL)
  247.         AdoptMenuLast(ev, menu);
  248.     else
  249.     {
  250.         FW_CPullDownMenu* next = (FW_CPullDownMenu*)fPullDownMenuList->After(afterMenu);
  251.         fPullDownMenuList->AddAfter(afterMenu, menu);
  252.         ODMenuID beforeID = next == NULL ? -1 : next->GetMenuID(ev);    
  253.         menu->PrivAttachedToMenuBar(ev, fODPart, this, beforeID);
  254.     }
  255. }
  256.  
  257. //----------------------------------------------------------------------------------------
  258. //    FW_CMenuBar::DeleteMenu
  259. //----------------------------------------------------------------------------------------
  260.  
  261. void FW_CMenuBar::DeleteMenu(Environment* ev, FW_CPullDownMenu* menuToDelete)
  262. {
  263.     FW_ASSERT(menuToDelete != NULL);
  264.  
  265.     DetachMenu(ev, menuToDelete);
  266.     delete menuToDelete;
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270. //    FW_CMenuBar::DeleteAll
  271. //----------------------------------------------------------------------------------------
  272.  
  273. void FW_CMenuBar::DeleteAll(Environment* ev)
  274. {
  275.     FW_CPullDownMenu *menu;
  276.     while ((menu = fPullDownMenuList->First()) != NULL)
  277.     {
  278.         DeleteMenu(ev, menu);
  279.     }
  280. }
  281.  
  282. //----------------------------------------------------------------------------------------
  283. //    FW_CMenuBar::RemoveItem
  284. //----------------------------------------------------------------------------------------
  285.  
  286. void FW_CMenuBar::RemoveItem(Environment* ev, ODCommandID commandID)
  287. {
  288.     FW_CMenuItem* item = this->GetMenuItemFromCommand(ev, commandID);
  289.     FW_ASSERT(item);
  290.     
  291.     FW_CPullDownMenu* menu = item->GetOwnerMenu(ev);
  292.     menu->RemoveItem(ev, item->GetIndex(ev));
  293. }
  294.  
  295. //----------------------------------------------------------------------------------------
  296. //    FW_CMenuBar::DetachMenu
  297. //----------------------------------------------------------------------------------------
  298.  
  299. void FW_CMenuBar::DetachMenu(Environment* ev, FW_CPullDownMenu* menuToDetach)
  300. {
  301.     FW_ASSERT(menuToDetach != NULL);
  302.     
  303.     fODMenuBar->RemoveMenu(ev, menuToDetach->GetMenuID(ev));
  304.     
  305.     fPullDownMenuList->Remove(menuToDetach);
  306.     menuToDetach->PrivDetachedFromMenuBar(ev, this);
  307. }
  308.  
  309. //----------------------------------------------------------------------------------------
  310. //    FW_CMenuBar::GetMenuKey
  311. //----------------------------------------------------------------------------------------
  312.  
  313. FW_MenuKey FW_CMenuBar::GetMenuKey(Environment* ev, ODCommandID cmdNumber) const
  314. {
  315. #ifdef FW_BUILD_MAC
  316.     FW_MenuKey menuKey;
  317.     
  318.     ODMenuID menuID;
  319.     ODMenuItemID menuItem;
  320.     fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
  321.     
  322.     ::GetItemCmd(GetMenuHandle(menuID), menuItem, &menuKey);
  323.     return menuKey;
  324. #endif
  325.  
  326. #ifdef FW_BUILD_WIN
  327.     return 0;                    // [HLX] no way yet to parse accelerator table
  328. #endif
  329. }
  330.  
  331. //----------------------------------------------------------------------------------------
  332. //    FW_CMenuBar::AcquireODMenuBar
  333. //----------------------------------------------------------------------------------------
  334.  
  335. ODMenuBar* FW_CMenuBar::AcquireODMenuBar(Environment* ev) const
  336. {
  337. #if FW_OPENDOC_VERSION >= FW_OPENDOC_DR3
  338.     fODMenuBar->Acquire(ev);
  339. #else
  340.     fODMenuBar->IncrementRefCount(ev);
  341. #endif
  342.     return fODMenuBar;
  343. }
  344.  
  345. //----------------------------------------------------------------------------------------
  346. //    FW_CMenuBar::FindMenuWithID
  347. //----------------------------------------------------------------------------------------
  348.  
  349. FW_CPullDownMenu* FW_CMenuBar::FindMenuWithID(Environment* ev, ODMenuID menuID) const
  350. {
  351.     // ----- Search the top level first -----
  352.     FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
  353.     FW_CPullDownMenu* pullDownMenu;
  354.     for (pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  355.     {
  356.         if (pullDownMenu->GetMenuID(ev) == menuID)
  357.             return pullDownMenu;
  358.     }
  359.     
  360.     // ----- Then search subMenus -----
  361.     for (pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  362.     {
  363.         FW_CPullDownMenu* menu = pullDownMenu->PrivFindMenuWithID(ev, menuID);
  364.         if (menu)
  365.             return menu;
  366.     }
  367.     
  368.     return NULL;
  369. }
  370.  
  371. #ifdef FW_BUILD_MAC
  372. //----------------------------------------------------------------------------------------
  373. //    FW_CMenuBar::MacEnableMenuBar
  374. //----------------------------------------------------------------------------------------
  375. //    This is specific for modal dialogs on the Mac
  376.  
  377. void FW_CMenuBar::MacEnableMenuBar(Environment* ev, FW_Boolean enable)
  378. {
  379.     // ----- Apple & OpenDoc Menus -----
  380.     fODMenuBar->EnableCommand(ev, kODCommandAppleMenu, enable);
  381.     fODMenuBar->EnableCommand(ev, kODCommandEditMenu, enable);
  382.     fODMenuBar->EnableCommand(ev, kODCommandDocumentMenu, enable);
  383.  
  384.     // ----- Then custom menus -----
  385.     FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
  386.     for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  387.     {
  388.         if (enable)
  389.             ::EnableItem(GetMenuHandle(pullDownMenu->GetMenuID(ev)), 0);
  390.         else
  391.             ::DisableItem(GetMenuHandle(pullDownMenu->GetMenuID(ev)), 0);
  392.     }
  393.     
  394.     ::InvalMenuBar();
  395. }
  396. #endif
  397.  
  398. //----------------------------------------------------------------------------------------
  399. //    FW_CMenuBar::EnableCommand
  400. //----------------------------------------------------------------------------------------
  401.  
  402. void FW_CMenuBar::EnableCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable)
  403. {
  404. #ifdef FW_BUILD_MAC
  405.     // [jkp] menus are not trivially cross platform
  406.     fODMenuBar->EnableCommand(ev, cmdNumber, enable);
  407. #endif
  408. #ifdef FW_BUILD_MAC
  409.     PrivMacEnableParentItem(ev, cmdNumber);
  410. #endif
  411. }
  412.  
  413. #ifdef FW_BUILD_MAC
  414. //----------------------------------------------------------------------------------------
  415. //    FW_CMenuBar::PrivMacEnableParentItem
  416. //----------------------------------------------------------------------------------------
  417.  
  418. void FW_CMenuBar::PrivMacEnableParentItem(Environment* ev, ODCommandID cmdNumber)
  419. {
  420.     ODMenuID menuID;
  421.     ODMenuItemID menuItem;
  422.     
  423.     fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
  424.     
  425.     FW_CPullDownMenu* menu = this->FindMenuWithID(ev, menuID);
  426.     if (menu == NULL)
  427.         return;
  428.         
  429.     FW_CMenuItem* parentItem = menu->GetParentMenuItem(ev);
  430.  
  431.     while (parentItem != NULL)                    // enable/disable parent menu
  432.     {    
  433.         ODPlatformMenu platformMenu = menu->GetPlatformMenu(ev);
  434.         long flags = (*platformMenu)->enableFlags;
  435.         
  436.         if ((flags & 0xFFFFFFFE) != 0)            // If any items enabled,
  437.             flags |= 0x00000001;                // enable top level item
  438.         else                                    // No items enabled,
  439.             flags = 0x00000000;                    // disable top level item
  440.         
  441.         if ((flags & 0x00000001) != ((*platformMenu)->enableFlags & 0x00000001))
  442.         {
  443.             (*platformMenu)->enableFlags = flags;
  444.         }
  445.         
  446.         menu = parentItem->GetOwnerMenu(ev);
  447.         ODPlatformMenu parentMenu = menu->GetPlatformMenu(ev);
  448.         if ((flags & 0xFFFFFFFE) != 0)    // if any items enabled
  449.             ::EnableItem(parentMenu, parentItem->GetIndex(ev));
  450.         else
  451.             ::DisableItem(parentMenu, parentItem->GetIndex(ev));
  452.     
  453.         // Check parent's parent
  454.         parentItem = menu->GetParentMenuItem(ev);
  455.     }
  456. }
  457. #endif
  458.  
  459. //----------------------------------------------------------------------------------------
  460. //    FW_CMenuBar::GetMenuItemFromCommand
  461. //----------------------------------------------------------------------------------------
  462.  
  463. FW_CMenuItem* FW_CMenuBar::GetMenuItemFromCommand(Environment* ev, ODCommandID cmdNumber) const
  464. {
  465.     FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
  466.     for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  467.     {
  468.         FW_CMenuItem* menuItem = pullDownMenu->PrivGetMenuItem(ev, cmdNumber);
  469.         if (menuItem != NULL)
  470.             return menuItem;
  471.     }    
  472.     return NULL;    
  473. }
  474.  
  475. //----------------------------------------------------------------------------------------
  476. //    FW_CMenuBar::ToggleItem
  477. //----------------------------------------------------------------------------------------
  478.  
  479. void FW_CMenuBar::ToggleItem(Environment* ev, 
  480.                             ODCommandID cmdNumber, 
  481.                             FW_Boolean toggleState)
  482. {
  483.     FW_CMenuItem* menuItem = GetMenuItemFromCommand(ev, cmdNumber);
  484.     FW_ASSERT(menuItem != NULL);
  485.     
  486. #ifdef FW_DEBUG
  487.     FW_CToggleItem* toggleItem = FW_DYNAMIC_CAST(FW_CToggleItem, menuItem);
  488.     FW_ASSERT(toggleItem);
  489.     toggleItem->ToggleItem(ev, toggleState);
  490. #else
  491.     ((FW_CToggleItem*)menuItem)->ToggleItem(ev, toggleState);
  492. #endif
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. //    FW_CMenuBar::DisableAll
  497. //----------------------------------------------------------------------------------------
  498.  
  499. void FW_CMenuBar::DisableAll(Environment* ev)
  500. {
  501.     FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
  502.     for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  503.     {
  504.         pullDownMenu->DisableAll(ev);
  505.     }    
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. //    FW_CMenuBar::EnableAll
  510. //----------------------------------------------------------------------------------------
  511.  
  512. void FW_CMenuBar::EnableAll(Environment* ev)
  513. {
  514.     FW_TOrderedCollectionIterator<FW_CPullDownMenu> ite(fPullDownMenuList);
  515.     for (FW_CPullDownMenu* pullDownMenu = ite.First(); ite.IsNotComplete(); pullDownMenu = ite.Next())
  516.     {
  517.         pullDownMenu->EnableAll(ev);
  518.     }    
  519. }
  520.  
  521. //----------------------------------------------------------------------------------------
  522. //    FW_CMenuBar::CheckCommand
  523. //----------------------------------------------------------------------------------------
  524.  
  525. void FW_CMenuBar::CheckCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean check)
  526. {
  527. #ifdef FW_BUILD_MAC
  528.     // [jkp] menus are not trivially cross platform
  529.     fODMenuBar->CheckCommand(ev, cmdNumber, check);
  530. #endif
  531. }
  532.  
  533. //----------------------------------------------------------------------------------------
  534. //    FW_CMenuBar::EnableAndCheckCommand
  535. //----------------------------------------------------------------------------------------
  536.  
  537. void FW_CMenuBar::EnableAndCheckCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable, FW_Boolean check)
  538. {
  539. #ifdef FW_BUILD_MAC
  540.     // [jkp] menus are not trivially cross platform
  541.     fODMenuBar->EnableAndCheckCommand(ev, cmdNumber, enable, check);
  542. #endif
  543.  
  544. #ifdef FW_BUILD_MAC
  545.     PrivMacEnableParentItem(ev, cmdNumber);
  546. #endif
  547. }
  548.  
  549. //----------------------------------------------------------------------------------------
  550. //    FW_CMenuBar::EnableAndToggleCommand
  551. //----------------------------------------------------------------------------------------
  552.  
  553. void FW_CMenuBar::EnableAndToggleCommand(Environment* ev, ODCommandID cmdNumber, FW_Boolean enable, FW_Boolean toggleState)
  554. {
  555.     EnableCommand(ev, cmdNumber, enable);
  556.     ToggleItem(ev, cmdNumber, toggleState);
  557. }
  558.  
  559. //----------------------------------------------------------------------------------------
  560. //    FW_CMenuBar::SetItemString
  561. //----------------------------------------------------------------------------------------
  562.  
  563. void FW_CMenuBar::SetItemString(Environment* ev, ODCommandID commandID, const FW_CString& itemString)
  564. {
  565. #ifdef FW_BUILD_MAC
  566.     // [jkp] menus are not trivially cross platform
  567.     fODMenuBar->SetItemString(ev, commandID, itemString.RevealODIText());
  568. #endif
  569. }
  570.  
  571. //----------------------------------------------------------------------------------------
  572. //    FW_CMenuBar::GetItemString
  573. //----------------------------------------------------------------------------------------
  574.  
  575. void FW_CMenuBar::GetItemString(Environment* ev, ODCommandID commandID, FW_CString& itemString) const
  576. {
  577. #ifdef FW_BUILD_MAC
  578.     ODIText intlText;
  579.     fODMenuBar->GetItemString(ev, commandID, &intlText);
  580.  
  581.     // Fix up locale info
  582.     if (GetITextScriptCode(&intlText) == smSystemScript)
  583.     {
  584.         // Convert smSystemScript (-1) to an actual script code
  585.         long systemScriptCode = ::GetScriptManagerVariable(smSysScript);
  586.         SetITextScriptCode(&intlText, systemScriptCode);
  587.     }
  588.     if (GetITextLangCode(&intlText) == langEnglish && GetITextScriptCode(&intlText) != smRoman)
  589.     {
  590.         // Get a language code that goes with the intlText's script code
  591.         SetITextLangCode(&intlText, (ODLangCode) ::GetScriptVariable(GetITextScriptCode(&intlText), smScriptLang));
  592.     }
  593.  
  594.     itemString = &intlText;
  595. #endif
  596.  
  597. #ifdef FW_BUILD_WIN
  598.     // [MEB] Not yet implemented
  599.     FW_UNUSED(ev);
  600.     FW_UNUSED(commandID);
  601.     FW_UNUSED(itemString);
  602. #endif
  603. }
  604.  
  605. //----------------------------------------------------------------------------------------
  606. //    FW_CMenuBar::GetAboutString
  607. //----------------------------------------------------------------------------------------
  608. FW_CString FW_CMenuBar::GetAboutString(Environment*) const
  609. {
  610.     return fAboutString;
  611. }
  612.  
  613. //----------------------------------------------------------------------------------------
  614. //    FW_CMenuBar::SetMenuKey
  615. //----------------------------------------------------------------------------------------
  616.  
  617. void FW_CMenuBar::SetMenuKey(Environment* ev, ODCommandID cmdNumber, FW_MenuKey menuKey)
  618. {
  619. #ifdef FW_BUILD_MAC
  620.     ODMenuID menuID;
  621.     ODMenuItemID menuItem;
  622.     fODMenuBar->GetMenuAndItem(ev, cmdNumber, &menuID, &menuItem);
  623.     MenuHandle menuHandle = ::GetMenuHandle(menuID);
  624.     FW_ASSERT(menuHandle);
  625.  
  626.     // Check for an existing key code, or other code ($1B submenu; $1C script code; $1D, $1E icon)
  627.     FW_MenuKey currentKey;
  628.     ::GetItemCmd(menuHandle, menuItem, ¤tKey);
  629.  
  630.     // If the current value is a special code, don't change it
  631.     if (currentKey == FW_kNoKeyEquivalent || currentKey > 32)
  632.         ::SetItemCmd(menuHandle, menuItem, menuKey & FW_kPrivMacMenuKeyCharMask);
  633. #endif
  634.  
  635. #ifdef FW_BUILD_WIN
  636.     // [MEB] Not yet implemented
  637.     FW_UNUSED(ev);
  638.     FW_UNUSED(cmdNumber);
  639.     FW_UNUSED(menuKey);
  640. #endif
  641. }
  642.  
  643. //----------------------------------------------------------------------------------------
  644. //    FW_CMenuBar::PrivGetNewMenuID
  645. //----------------------------------------------------------------------------------------
  646. ODMenuID FW_CMenuBar::PrivGetNewMenuID(Environment* ev)
  647. {
  648.     // Fast (normal) case - just keep incrementing the ID
  649.     if (fNextMenuID < FW_kLastMenuID)
  650.         return fNextMenuID++;
  651.  
  652.     // Slow case - look for an unused ID
  653.     ODMenuID id = FW_kLastMenuID;
  654.     do
  655.     {
  656.         if (!FindMenuWithID(ev, id))
  657.             return id;
  658.         id--;
  659.     }
  660.     while (id >= FW_kFirstMenuID);
  661.  
  662.     // If we reach this point, there are no unused menu ids left!
  663.     id = FW_kLastMenuID;
  664.     FW_ASSERT(id != FW_kLastMenuID);
  665.     return id;    // gotta return something, or the compiler will complain
  666. }
  667.